

#ifndef _TCP_CONNECTION_H_
#define _TCP_CONNECTION_H_

#include "Buffer.hpp"
#include "Callbacks.hpp"
#include "InetAddress.hpp"
#include "Timestamp.hpp"
#include "noncopyable.hpp"
#include <atomic>
#include <memory>
#include <string>

namespace zephyr {

class Channel;
class EventLoop;
class Socket;

class TcpConnection : noncopyable, public std::enable_shared_from_this<TcpConnection> {
  public:

    TcpConnection(EventLoop *loop, const std::string &nameArg,
                  int sockfd, const InetAddress &localaddr, const InetAddress &peeraddr);
    ~TcpConnection();

    EventLoop *getLoop() const { return m_loop; }
    const std::string &name() const { return m_name; }
    const InetAddress &localAddress() const { return m_localaddr; }
    const InetAddress &peerAddress() const { return m_peeraddr; }

    bool connected() const { return m_state == Connected;}

    void send(const std::string &buf);
    void shutdown();

    void setConnectionCallbakc(const ConnectionCallback &cb) {
        m_connectionCallback = cb;
    }
    void setMessageCallback(const MessageCallback &cb) {
        m_messageCallback = cb;
    }
    void setWriteCompleteCallback(const WriteCompleteCallback &cb) {
        m_writeCompletCallback = cb;
    }
    void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t highWaterMark) {
        m_highWaterMarkCallback = cb;
        m_highWaterMark = highWaterMark;
    }
    void setCloseCallback(const CloseCallback &cb) {
        m_closeCallback = cb;
    }

    void connectEstablished();
    void connectDestroyed();

  private:
    enum State {
        Disconnected, // 以及断开连接
        Connecteing,  // 正在连接
        Connected,    // 已经连接
        Disconnecting // 正在断开连接
    };
    void setState(State state) { m_state = state; }

    void handleRead(Timestamp);
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const void *data, size_t len);
    void shutdownInLoop();

  private:
    EventLoop *m_loop;
    const std::string m_name;
    std::atomic_int m_state;
    bool m_reading;

    std::unique_ptr<Socket> m_socket;
    std::unique_ptr<Channel> m_channel;

    const InetAddress m_localaddr;
    const InetAddress m_peeraddr;

    ConnectionCallback m_connectionCallback;
    MessageCallback m_messageCallback;
    WriteCompleteCallback m_writeCompletCallback;
    HighWaterMarkCallback m_highWaterMarkCallback;
    CloseCallback m_closeCallback;
    size_t m_highWaterMark;

    Buffer m_inputBuffer;
    Buffer m_outputBuffer;
};

}

#endif // _TCP_CONNECTION_H_